home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
crit.arc
/
CRIT.ASM
next >
Wrap
Assembly Source File
|
1986-12-03
|
5KB
|
168 lines
;
; testcrit.asm - implements a 'setjmp' style critical error handler
; for Microsoft C. Implementation with other compilers should be trivial.
; define LARGE_CODE to compile for large code models
;
ifdef MMODEL
LARGECODE EQU 1
endif
ifdef LMODEL
LARGECODE EQU 1
endif
ifdef HMODEL
LARGECODE EQU 1
endif
_TEXT segment public 'CODE'
_DATA segment public 'DATA'
_DATA ends
assume cs:_TEXT,ds:_DATA
old_handler label dword
old_off dw ?
old_seg dw ?
critical equ 24H
savess dw ?
savesp dw ?
savebp dw ?
savesi dw ?
savedi dw ?
returnaddress dw ?
ifdef LARGE_CODE
returnsegment dw ?
endif
datasegment dw ?
extrasegment dw ?
counter dw 0
; crit_handler is where the critical error vector is pointed.
; it follows the suggestions found in the DOS technical reference handler,
; i.e. it calls the old handler, and decides what to do on the basis of the
; value returned in AL
public crit_handler
crit_handler proc near
pushf ; push flags to simulate s/w interrupt
call dword ptr cs:old_handler ; call the old handler
cmp al,2 ; is this an abort?
je do_abort ; if it is, handle abort
iret ; if not, just iret
do_abort:
; otherwise, restore environment
cli ; disable interrupts
; restore all important registers to the values they had upon entry
; into setup_crit, set AX to -1 and return
mov ss,cs:savess
mov sp,cs:savesp
mov bp,cs:savebp
mov si,cs:savesi
mov di,cs:savedi
mov ds,cs:datasegment
mov es,cs:extrasegment
mov bx,cs:returnaddress ; pick up return address
mov ax,-1 ; return -1
sti ; enable interrupts
ifdef LARGE_CODE
jmp dword ptr cs:returnaddress
else
jmp bx
endif
crit_handler endp
;
; setup_crit - sets up the critical error handler.
; When this is called initially it will return 0.
; If a critical error occurs, and the user responds with 'abort'
; to the abort, retry, ignore message, then it will return -1.
; This is very similar to the setjmp/longjmp non-local goto interface in
; the standard C library
;
public _setup_crit
ifdef LARGE_CODE
_setup_crit proc far
else
_setup_crit proc near
endif
; the counter variable is an interlock - if you call setup_crit
; if another call to setup_crit is already pending, then restore_crit will
; be called in order to restore the old vector before installing the new
; one.
cmp cs:counter,0 ; have we been here before?
je continue ; if not, keep going
ifdef LARGE_CODE
call far ptr _restore_crit
else
call _restore_crit ; otherwise restore old handler 1st
endif
continue:
inc cs:counter ; bump the counter
push es ; save registers munged
push ds ;
push si ;
xor ax,ax ; address interrupt vectors
mov ds,ax
mov bx,critical*4 ; offset of critical error handler
les si,[bx] ; load into es:si
mov cs:old_off,si ; save offset
mov cs:old_seg,es ; save segment
mov word ptr [bx],offset crit_handler ; install new handler
mov 2[bx],cs ; handler segment
pop si ; restore munged variables
pop ds ;
pop es ;
; save the relevant calling environment, which consists of
; ss,sp,bp (stack environment) si,di (possible register vars)
; and ds,es (data segments)
mov cs:savess,ss
mov cs:savesp,sp
mov cs:savebp,bp
mov cs:savesi,si
mov cs:savedi,di
mov cs:datasegment,ds
mov cs:extrasegment,es
xor ax,ax ; return 0
pop bx ; get return address
mov cs:returnaddress,bx ; save it
ifdef LARGE_CODE
pop bx ; get return segment
mov cs:returnsegment,bx
jmp dword ptr cs:returnaddress
else
jmp bx ; go to return address
endif
_setup_crit endp
public _restore_crit
ifdef LARGE_CODE
_restore_crit proc far
else
_restore_crit proc near
endif
; check the counter to make sure setup_crit has already been called
cmp cs:counter,1 ; has it been called?
je restore ; yes, restore environment
ret ; no, do nothing
restore:
dec cs:counter ; make counter 0
push es ; save registers munged
push ds ;
push si ;
xor ax,ax ; address interrupt vectors
mov ds,ax ;
les si,cs:old_handler ; pick up old handler into es:si
mov bx,critical*4 ; address critical vector
mov [bx],si ; poke old handler back in
mov 2[bx],es ;
pop si ; restore munged registers
pop ds ;
pop es ;
ret ; go away
_restore_crit endp
_TEXT ends
end